我想使用promise ,但我有一个回调API,格式如下:

1.DOM加载或其他一次性事件:

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

};

2.普通回调:

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

3. node 样式回调("nodeback"):

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

4.带 node 样式回调的整库:

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

如何在promises中使用API,如何"promise "它?

推荐答案

promise 有状态,开始时是待定的,可以解决以下问题:

  • fulfilled表示计算成功完成.
  • rejected意味着计算失败.

promise 返回函数should never throw,则它们应该返回拒绝.从promise 返回函数抛出将迫使您同时使用} catch {and.catch.使用简化API的人们并不指望会抛出promise .如果您不确定异步API在JS中是如何工作的,请先使用see this answer.

1.DOM加载或其他一次性事件:

因此,创建promise 通常意味着指定它们何时结算——也就是说,当它们移动到满足或拒绝阶段时,表明数据可用(并且可以使用.then访问).

通过支持Promise个构造函数的现代promise实现,如本机ES6 promises:

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

然后,您可以按如下方式使用生成的promise :

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

对于支持deferred的库(在这里我们使用$q作为示例,但稍后我们也将使用jQuery):

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

或者使用类似于jQuery的API,钩住一次发生的事件:

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

2.普通回调:

这些API相当常见,因为Well…回调在JS中很常见.让我们看一下onSuccessonFail的常见情况:

function getUserData(userId, onLoad, onFail) { …

通过支持Promise个构造函数的现代promise实现,如本机ES6 promises:

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

使用支持延迟的库(我们在本例中使用jQuery,但上面也使用了$q):

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

jQuery还提供了$.Deferred(fn)表单,它的优点是允许我们编写一个非常接近new Promise(fn)表单的表达式,如下所示:

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

注意:这里我们利用了jQuery的resolvereject方法是"可分离的"这一事实;也就是说,它们被绑定到jQuery的instance.延迟().并非所有LIB都提供此功能.

3. node 样式回调("nodeback"):

node 样式回调(NodeBack)有一种特定的格式,其中回调始终是最后一个参数,其第一个参数是错误.让我们先手动提示一个:

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

收件人:

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

使用deferreds可以执行以下操作(本例使用q,尽管q现在支持新语法which you should prefer):

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;   
}

一般来说,您不应该太多地手动代理,大多数在Node 8+中考虑到Node和本机promise 而设计的Promise库都有一个内置的方法来代理nodeback.例如

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

4.带 node 样式回调的整库:

这里没有金科玉律,你一个接一个地promise .然而,一些promise实现允许您批量执行此操作,例如在Bluebird中,将nodeback API转换为promise API非常简单:

Promise.promisifyAll(API);

或每Node人中有native promises人:

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}), {});

注:

  • 当然,当你是.then人时,你不需要做出promise .从.then处理程序返回promise 将解决或拒绝该promise 的价值..then人投掷也是一种很好的练习,会拒绝promise ——这就是著名的promise 投掷安全.
  • 在实际onload的情况下,您应该使用addEventListener而不是onX.

Javascript相关问答推荐

如何在react-Router-dom 6中Forking 路由?

React:如何将表格收件箱正确渲染为表格主体内的组件?

如何使用CSS和JavaScript创建粘性、凝聚力的形状到形状(容器)变形?

更新Reduxstore 中的状态变量,导致整个应用程序出现不必要的重新渲染

如果没有尾随斜线,托管在收件箱中的React/Vite将无法工作

基于每个索引迭代嵌套对象

在NextJS中使用计时器循环逐个打开手风琴项目?

如何获取转换字节的所有8位?

Angular:动画不启动

如何在JavaScript文件中使用Json文件

如何使用子字符串在数组中搜索重复项

我在Django中的视图中遇到多值键错误

Puppeteer上每页的useProxy返回的不是函数/构造函数

Jest toHaveBeenNthCalledWith返回当前设置的变量值,而不是调用时的值

使用父标签中的Find函数查找元素

React:防止useContext重新渲染整个应用程序或在组件之间共享数据而不重新渲染所有组件

ngOnChanges仅在第二次调用时才触发

如何修复错误&语法错误:不能在纯react 项目中JEST引发的模块&之外使用导入语句?

如何在TransformControls模式下只保留箭头进行翻译?

是否有静态版本的`instanceof`?