本文翻译自:How do I convert an existing callback API to promises?

I want to work with promises but I have a callback API in a format like: 我想使用Promise,但是我有一个类似以下格式的回调API:

1. DOM load or other one time event: 1. DOM加载或其他一次事件:

window.onload; // set to callback
...
window.onload = function() {};

2. Plain callback: 2.普通回调:

function request(onChangeHandler) {...
}
request(function() {// change happened...
});

3. Node style callback ("nodeback"): 3.节点样式回调(“ nodeback”):

function getStuff(dat, callback) {...
}
getStuff("dataParam", function(err, data) {...
})

4. A whole library with node style callbacks: 4.带有节点样式回调的整个库:

API;
API.one(function(err, data) {API.two(function(err, data2) {API.three(function(err, data3) {...});});
});

How do I work with the API in promises, how do I "promisify" it? 如何在promise中使用API​​,如何“承诺”它?


#1楼

参考:https://stackoom.com/question/1WUQK/如何将现有的回调API转换为Promise


#2楼

Promises have state, they start as pending and can settle to: 承诺有状态,它们从待定状态开始,可以解决:

  • fulfilled meaning that the computation completed successfully. 完成意味着计算成功完成。
  • rejected meaning that the computation failed. 拒绝表示计算失败。

Promise returning functions should never throw , they should return rejections instead. 承诺返回函数绝不应该抛出 ,而应该返回拒绝。 Throwing from a promise returning function will force you to use both a } catch { and a .catch . 从promise返回函数抛出将迫使您同时使用} catch { .catch People using promisified APIs do not expect promises to throw. 使用承诺的API的人们不会期望诺言。 If you're not sure how async APIs work in JS - please see this answer first. 如果您不确定JS中异步API的工作方式-请首先查看此答案 。

1. DOM load or other one time event: 1. DOM加载或其他一次事件:

So, creating promises generally means specifying when they settle - that means when they move to the fulfilled or rejected phase to indicate the data is available (and can be accessed with .then ). 因此,创建承诺通常意味着指定何时结算-即何时进入承诺阶段或拒绝阶段以指示数据可用(并且可以通过.then访问)。

With modern promise implementations that support the Promise constructor like native ES6 promises: 使用支持Promise构造函数的现代Promise实现(例如本机ES6 Promise

function load() {return new Promise(function(resolve, reject) {window.onload = resolve;});
}

You would then use the resulting promise like so: 然后,您将使用产生的承诺,如下所示:

load().then(function() {// Do things after onload
});

With libraries that support deferred (Let's use $q for this example here, but we'll also use jQuery later): 使用支持延迟的库(让我们在此示例中使用$ q,但稍后我们还将使用jQuery):

function load() {var d = $q.defer();window.onload = function() { d.resolve(); };return d.promise;
}

Or with a jQuery like API, hooking on an event happening once: 或者使用jQuery之类的jQuery,将一次事件挂起:

function done() {var d = $.Deferred();$("#myObject").once("click",function() {d.resolve();});return d.promise();
}

2. Plain callback: 2.普通回调:

These APIs are rather common since well… callbacks are common in JS. 这些API相当常见,因为……在JS中回调很常见。 Let's look at the common case of having onSuccess and onFail : 让我们看一下具有onSuccessonFail的常见情况:

function getUserData(userId, onLoad, onFail) { …

With modern promise implementations that support the Promise constructor like native ES6 promises: 使用支持Promise构造函数的现代Promise实现(例如本机ES6 Promise

function getUserDataAsync(userId) {return new Promise(function(resolve, reject) {getUserData(userId, resolve, reject);});
}

With libraries that support deferred (Let's use jQuery for this example here, but we've also used $q above): 使用支持延迟的库(在此示例中,我们使用jQuery,但上面我们也使用$ q):

function getUserDataAsync(userId) {var d = $.Deferred();getUserData(userId, function(res){ d.resolve(res); }, function(err){ d.reject(err); });return d.promise();
}

jQuery also offers a $.Deferred(fn) form, which has the advantage of allowing us to write an expression that emulates very closely the new Promise(fn) form, as follows: jQuery还提供了$.Deferred(fn)形式,它的优点是允许我们编写一个非常接近new Promise(fn)形式的表达式,如下所示:

function getUserDataAsync(userId) {return $.Deferred(function(dfrd) {getUserData(userId, dfrd.resolve, dfrd.reject);}).promise();
}

Note: Here we exploit the fact that a jQuery deferred's resolve and reject methods are "detachable"; 注意:这里我们利用了一个事实,即jQuery deferred的resolvereject方法是“可分离的”。 ie. 即。 they are bound to the instance of a jQuery.Deferred(). 它们绑定到jQuery.Deferred()的实例 Not all libs offer this feature. 并非所有库都提供此功能。

3. Node style callback ("nodeback"): 3.节点样式回调(“ nodeback”):

Node style callbacks (nodebacks) have a particular format where the callbacks is always the last argument and its first parameter is an error. 节点样式回调(nodebacks)具有特定的格式,其中回调始终是最后一个参数,而其第一个参数是错误。 Let's first promisify one manually: 让我们首先手动分配一个:

getStuff("dataParam", function(err, data) { …

To: 至:

function getStuffAsync(param) {return new Promise(function(resolve, reject) {getStuff(param, function(err, data) {if (err !== null) reject(err);else resolve(data);});});
}

With deferreds you can do the following (let's use Q for this example, although Q now supports the new syntax which you should prefer ): 使用deferred,您可以执行以下操作(尽管本例中Q现在支持您应首选使用的新语法,但让本示例使用Q):

function getStuffAsync(param) {var d = Q.defer();getStuff(param, function(err, data) {if (err !== null) d.reject(err);else d.resolve(data);});return d.promise;
}

In general, you should not promisify things manually too much, most promise libraries that were designed with Node in mind as well as native promises in Node 8+ have a built in method for promisifying nodebacks. 通常,您不应该过多地手动分配内容,大多数基于Node设计的Promise库以及Node 8+中的本机Promise具有内置的用于使NodeBback富集的方法。 For example 例如

var getStuffAsync = Promise.promisify(getStuff); // Bluebird
var getStuffAsync = Q.denodeify(getStuff); // Q
var getStuffAsync = util.promisify(getStuff); // Native promises, node only

4. A whole library with node style callbacks: 4.带有节点样式回调的整个库:

There is no golden rule here, you promisify them one by one. 这里没有黄金法则,您一一承诺。 However, some promise implementations allow you to do this in bulk, for example in Bluebird, converting a nodeback API to a promise API is as simple as: 但是,某些promise实现允许您批量执行此操作,例如在Bluebird中,将nodeback API转换为promise API很简单:

Promise.promisifyAll(API);

Or with native promises in Node : 或在Node中具有本机承诺

const { promisify } = require('util');
const promiseAPI = Object.entries(API).map(([key, v]) => ({key, fn: promisify(v)})).reduce((o, p) => Object.assign(o, {[p.key]: p.fn}), {});

Notes: 笔记:

  • Of course, when you are in a .then handler you do not need to promisify things. 当然,当你在一个.then处理你不需要promisify事情。 Returning a promise from a .then handler will resolve or reject with that promise's value. .then处理程序返回一个诺言将解决或拒绝该诺言的值。 Throwing from a .then handler is also good practice and will reject the promise - this is the famous promise throw safety. .then处理程序中抛出也是很好的做法,并且会拒绝诺言-这就是著名的诺言抛出安全性。
  • In an actual onload case, you should use addEventListener rather than onX . 在实际的onload情况下,应该使用addEventListener而不是onX

#3楼

I don't think the window.onload suggestion by @Benjamin will work all the time, as it doesn't detect whether it is called after the load. 我认为@Benjamin的window.onload建议不会一直有效,因为它无法检测到加载后是否被调用。 I have been bitten by that many times. 我被很多次咬伤了。 Here is a version which should always work: 这是一个应该始终有效的版本:

function promiseDOMready() {return new Promise(function(resolve) {if (document.readyState === "complete") return resolve();document.addEventListener("DOMContentLoaded", resolve);});
}
promiseDOMready().then(initOnLoad);

#4楼

The Q library by kriskowal includes callback-to-promise functions. kriskowal的Q库包含应答回调函数。 A method like this: 这样的方法:

obj.prototype.dosomething(params, cb) {...blah blah...cb(error, results);
}

can be converted with Q.ninvoke 可以用Q.ninvoke转换

Q.ninvoke(obj,"dosomething",params).
then(function(results) {
});

#5楼

You can use JavaScript native promises with Node JS. 您可以将JavaScript本机Promise与Node JS一起使用。

My Cloud 9 code link: https://ide.c9.io/adx2803/native-promises-in-node 我的Cloud 9代码链接: https : //ide.c9.io/adx2803/native-promises-in-node

/**
* Created by dixit-lab on 20/6/16.
*/var express = require('express');
var request = require('request');   //Simplified HTTP request client.var app = express();function promisify(url) {return new Promise(function (resolve, reject) {request.get(url, function (error, response, body) {if (!error && response.statusCode == 200) {resolve(body);}else {reject(error);}})});
}//get all the albums of a user who have posted post 100
app.get('/listAlbums', function (req, res) {//get the post with post id 100promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {var obj = JSON.parse(result);return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')}).catch(function (e) {console.log(e);}).then(function (result) {res.end(result);})
})var server = app.listen(8081, function () {var host = server.address().addressvar port = server.address().portconsole.log("Example app listening at http://%s:%s", host, port)
})//run webservice on browser : http://localhost:8081/listAlbums

#6楼

When you have a few functions that take a callback and you want them to return a promise instead you can use this function to do the conversion. 当您有一些需要回调的函数并且希望它们返回一个Promise时,您可以使用此函数进行转换。

function callbackToPromise(func){return function(){// change this to use what ever promise lib you are using// In this case i'm using angular $q that I exposed on a util modulevar defered = util.$q.defer();var cb = (val) => {defered.resolve(val);}var args = Array.prototype.slice.call(arguments);args.push(cb);    func.apply(this, args);return defered.promise;}
}

如何将现有的回调API转换为Promise?相关推荐

  1. 如何将小程序内置非promise API转换为promise对象(风袖小程序的学习)

    非常重要,便于项目大局观,使用es7的 async和await 如何将小程序内置非promise API转换为promise 这里是我封装的一个wx.request函数如何将wx.request转换成 ...

  2. 小程序API的Promise化

    小程序官方提供的异步API都是基于回调函数来实现的,如大量的使用回调函数就会造成 回调地狱 的问题,同时代码的可读性和可维护性差,那么这篇内容主要来讲小程序API的Promise化,Promise是一 ...

  3. 微信小程序API的Promise化及全局状态管理MobX

    文章目录 API的Promise化 创建promise化的对象 全局状态管理 创建 页面中绑定 页面中使用 组件中绑定 组件中使用 API的Promise化 默认情况下小程序官方提供的API都是基于回 ...

  4. 【JavaScript】回调地狱、Promise

    文章目录 1. 回调函数 2. 异步任务 3. 回调地狱 4. Promise 4.1 Promise定义 4.2 Promise基础用法 4.2.1 生成Promise实例 4.2.2 Promis ...

  5. 回调地狱和Promise

    目录 1.回调地狱callback-hell 由于fs.readFile是异步操作,所以你不能判断下面三个文件的执行顺序 var fs = require('fs')fs.readFile('./da ...

  6. SQL Server扩展事件(Extended Events)-- 将现有 SQL 跟踪脚本转换为扩展事件会话

    SQL Server扩展事件(Extended Events)-- 将现有 SQL 跟踪脚本转换为扩展事件会话 如果您具有想要转换为扩展事件会话的现有 SQL 跟踪脚本,则可以使用本主题中的过程创建等 ...

  7. api pdo php,从PHP Mysql API转换为PDO时如何处理数据类型

    我正在将我们的站点从PHP Mysql API转换为PDO,并且遇到了数据类型问题. 以前,我们对所有变量都进行了转义,就好像它们是字符串一样.例如, SET varname = '$varvalue ...

  8. ES6(三)——回调地狱和promise异步任务顺序执行(传参、错误处理)

    文章目录 方法一.回调函数(回调地狱) 方法二:promise 2.1异步任务传参(单个) 2.2异步任务传参(多个) 2.3 错误处理 2.4 Promiss对象三大状态: (学名) 2.5 Pro ...

  9. 微信小程序-API的Promise化

    npm初始化 npm init -y 安装小程序的Promise包 1.使用腾讯官方出的第三方库实现小程序所有API 的 Promise 化 npm install --save miniprogra ...

最新文章

  1. nacos 负载策略_Spring Cloud Alibaba:Nacos 作为注册中心和配置中心使用
  2. 手把手教你用python抢票回家过年 !(附代码)
  3. websocket创建失败_SpringBoot2.2 实践WebSocket被不靠谱的百度搜索结果坑了多少人
  4. 关联关系和依赖关系的区别
  5. 算法笔记_065:分治法求逆序对(Java)
  6. Python类方法和静态方法
  7. 通过图标来识别网站用户指纹
  8. 游戏音效的发展和制作游戏音效的意义
  9. CentOS下使用命令行Web浏览器Links
  10. 大话西游,唐僧与悟空合伙创业,股权几何?
  11. RuntimeError: mat1 and mat2 shapes cannot be multiplied
  12. 追MM“23式”—— GOF 23种设计模式
  13. JavaScript 数据结构与算法(队列)
  14. 数据结构 —— 队列、栈、链表的区别
  15. 【Jmeter常用断言组件】
  16. numpy均匀分布_Numpy的基本操作
  17. OpenCV将视频转存为一帧帧的图片(Python)
  18. java校园导航_基于Android平台的校园导航系统
  19. 【OpenCV】获得视频的帧数、FPS以及按帧数将图片保存到本地
  20. 什么是HTTP协议及工作原理

热门文章

  1. 再论c++模板之类型识别之如何得到类型信息
  2. andriod 接入mqtt_Android 连接阿里云 mqtt失败
  3. Swift String字符串版本更新特性
  4. Swift中@IBDesignable/@IBInspectable的使用
  5. (005) java后台开发之Mac终端命令运行java
  6. (0060)iOS开发之iOS 9: UIStackView入门
  7. android列表集合点击事件,给ListeView列表中的每一个Item添加点击事件
  8. uniapp启动页,底部虚拟按钮向上闪一下的问题
  9. 批量启动关闭MS SQL 2005服务BAT
  10. java开发 中台